use std::fs::File;
use std::io::Read;
use std::path::Path;

use e_utils::cmd::Cmd;
use e_utils::fs::write_utf8;
use quick_xml::se::to_string;
use quick_xml::{de::from_str, se::to_string_with_root};
mod ty;
use serde::{Deserialize, Serialize};
use ty::*;

const OA3_CFG: &'static str = "OA3.cfg";
const BASE_INPUT_XML: &'static str = "FileBasedInputFile.xml";
const OA3TOOL: &'static str = "OA3Tool.exe";

fn main() -> e_utils::AnyResult<()> {
    let oa3: OA3 = open_xml(OA3_CFG)
        .map_err(|e| println!("{e}"))
        .unwrap_or_default();
    let oa3_str = to_string(&oa3)?;
    println!("{}", oa3_str);
    let mut base_input: FileBasedInputFile = open_xml(BASE_INPUT_XML)
        .map_err(|e| println!("{e}"))
        .unwrap_or_default();
    base_input.product_key = "product_key test".to_string();
    let base_input_str = to_string_with_root("Key", &base_input)?;
    println!("{}", base_input_str);
    write_utf8(&Path::new("test.xml").to_path_buf(), &oa3_str, true, false)?;
    write_utf8(
        &Path::new("test2.xml").to_path_buf(),
        &base_input_str,
        true,
        false,
    )?;
    let res = Cmd::new(OA3TOOL).args(["/Assemble",&format!("/Configfile={OA3_CFG}")]).set_type(e_utils::cmd::ExeType::WindowsExe).output()?;
    let xs = res.stdout;
    println!("{xs}");
    Ok(())
}

fn open_xml<T: Serialize + for<'de> Deserialize<'de>>(
    target: impl AsRef<Path>,
) -> e_utils::AnyResult<T> {
    let mut file = File::open(target)?;
    let mut xml_data = String::new();
    file.read_to_string(&mut xml_data)?;

    // 直接使用 xml_data，不需要复制
    let res: T = from_str(&xml_data)?;
    Ok(res)
}
